/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_RTP_UTIL_H
#define MK_RTP_UTIL_H
#include "MkUtil/MkBuffer.h"

#define  MkMaxRtpLen         1400
#define  RtcpCommonLen      4
#define  RtcpSRlen          24
#define  ReportBlockLen     24

typedef enum _rtp_type
{
    MkRtpSender = 1,
    MkRtpRecver = 2,
    MkRtpSendRecver = MkRtpSender | MkRtpRecver
}MkRtpType;

typedef enum _rtcp_packet_type
{
    //MkRtcpFir = 192, //lost I frame rfc2032
    //MkRtcpNack = 193, //resend lost packet rfc2032
    //MkRtcpSmptetc = 194, //rfc 5484
    //MkRtcpIj = 195,//rfc 5450
    MkRtcpSr = 200,
    MkRtcpRr = 201,
    MkRtcpSdes = 202,
    MkRtcpBye = 203,
    MkRtcpApp = 204,
    //MkRtcpRtpFb = 205, //rtp feedback rfc4585
    //MkRtcpPsFb = 206, //ps feedback rfc4585
    //MkRtcpXr = 207, //rfc 3611
    //MkRtcpAvb = 208,
    //MkRtcpRsi = 209, //rfc 5760
    //MkRtcpToken = 210, //rfc 6284
    //MkRtcpIdms = 211, //rfc7272
    //MkRtcpRgrs = 212, //rfc 8861
    //MkRtcpLimit = 223
}MkRtcpPacketType;

typedef enum _rtcp_sdes_type
{
    MkSdesEnd = 0,
    MkSdesCName = 1,
    MkSdesName = 2,
    MkSdesEmail = 3,
    MkSdesPhone = 4,
    MkSdesLoc = 5,
    MkSdesTool = 6,
    MkSdesNote = 7,
    MkSdesPriv = 8
}MkRtcpSdesType;

/*
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                 SSRC_1 (SSRC of first source)                 | report
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
    | fraction lost |       cumulative number of packets lost       |
    -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |           extended highest sequence number received           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      interarrival jitter                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         last SR (LSR)                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                   delay since last SR (DLSR)                  |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
typedef struct _rtcp_report_block
{
    Uint32              FirstSsrc;                      //4byte
    Uint8               FractionLost;                   //1byte
    Uint32              TotalLost;                      //3byte
    Uint32              LastSeq;                        //4byte
    Uint32              Jitter;                         //4byte  D(i,j)=(Rj-Ri)-(Sj-Si)=(Rj-Sj)-(Ri-Si) J=J+(|D(i-1,i)|-J)/16
    Uint32              Lsr;                            //4byte
    Uint32              Dlsr;                           //4byte
}MkRtcpReportBlock;

/*
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|    RC   |   PT=SR=200   |             length            | header
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         SSRC of sender                        |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    |              NTP timestamp, most significant word             | sender
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ info
    |             NTP timestamp, least significant word             |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         RTP timestamp                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                     sender's packet count                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      sender's octet count                     |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    :                       report block 1                          :
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    :                     report block 2-n ...                      :
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 */

typedef struct _rtcp_sender_report
{
    Uint32                          Ssrc;                         //4byte
    Uint64                          NtpTimeStamp;                 //8byte
    Uint32                          RtpTimeStamp;                 //4byte
    Uint32                          SenderPacketCount;            //4byte
    Uint32                          SenderOctetCount;             //4byte
    MkVector<MkRtcpReportBlock>     VecBlock;
}MkRtcpSenderReport;


/*
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|    RC   |   PT=RR=201   |             length            | header
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                     SSRC of packet sender                     |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    :                       report block 1                          :
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    :                     report block 2-n ...                      :
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
typedef struct _rtcp_receiver_report
{
    Uint32                          Ssrc;  //4byte
    MkVector<MkRtcpReportBlock>     VecBlock;
}MkRtcpReceptionReport;

/*
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|    SC   |  PT=SDES=202  |             length            | header
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    |                          SSRC/CSRC_1                          | chunk
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   1
    |                           SDES items                          |
    |                              ...                              |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    |                          SSRC/CSRC_2                          | chunk
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   2
    |                           SDES items                          |
    |                              ...                              |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/

typedef struct _rtcp_source_desc_item
{
    MkRtcpSdesType      DescType;           //1byte  MkRtcpSdesType
    //Uint8               Length;           //1byte DomainName len
    MkString            DomainName;         //Length  < 255
}MkRtcpSourceDescItem;

typedef struct _rtcp_source_description
{
    Uint32                                 Ssrc;     //first SSRC/CSRC
    MkMap<MkRtcpSdesType, MkRtcpSourceDescItem>     MapDescChunk;     //key desc type  header count  only support one desc per desctype
}MkRtcpSourceDescription;

/*
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |V=2|P|    SC   |   PT=BYE=203  |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           SSRC/CSRC                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :                              ...                              :
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |     length    |               reason for leaving             ... (opt)
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

typedef struct _rtcp_bye
{
    MkVector<Uint32>            VecSsrc;           // header count
    Uint8                       ReasonLen;
    MkString                    Reason;
}MkRtcpByeParam;

/*
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |V=2|P| subtype |   PT=APP=204  |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           SSRC/CSRC                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          name (ASCII)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                   application-dependent data                 ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   header count is app subtype
*/

typedef struct _rtcp_app
{
    Uint32          Ssrc;                         //4byte
    Uint32          Name;                         //4byte
    Uint32          DataLen;
    MkString        AppDependentData;             // 4 * x byte
}MkRtcpAppParam;


class MkApi CMkRtcpPacket
{
public:
    CMkRtcpPacket();
    ~CMkRtcpPacket();
    Uint32 Parse(Uint8 *pBuf, Uint32 nLen, OUT Uint32 &nUsed);

    const Uint8& GetVersion() const { return m_Version; }
    const Uint8& GetPadding()const { return m_Padding; }
    const Uint8& GetCount() const { return m_Count; }
    const Uint8& GetPayload() const { return m_Payload; }
    //const Uint16& GetLength() const { return m_Length; }

    Uint32 GetSsrc() const;

    void SetVersion(Uint8 Version) { m_Version = Version; }
    void SetPadding(Uint8 Padding) { m_Padding = Padding; }
    void SetCount(Uint8 Count) { m_Count = Count; }
    void SetPayload(Uint8 Payload) { m_Payload = Payload; }
    //void SetLength(Uint16 nLen) { m_Length = nLen; }

    const Uint32& GetSenderReportSsrc()const { return m_SenderReport.Ssrc; }
    const Uint64& GetSenderReportNtpTimeStamp() const { return m_SenderReport.NtpTimeStamp; }
    const Uint32& GetSenderReportRtpTimeStamp()const { return m_SenderReport.RtpTimeStamp; }
    const Uint32& GetSenderReportSenderPacketCount()const { return m_SenderReport.SenderPacketCount; }
    const Uint32& GetSenderReportSenderOctetCount()const { return m_SenderReport.SenderOctetCount; }
    const MkVector<MkRtcpReportBlock>& GetReportBlocks()const { return m_SenderReport.VecBlock; }

    void SetSenderReportSsrc(Uint32 Ssrc) { m_SenderReport.Ssrc = Ssrc; }
    void SetSenderReportNtpTimeStamp(Uint64 TimeStamp) { m_SenderReport.NtpTimeStamp = TimeStamp; }
    void SetSenderReportRtpTimeStamp(Uint32 TimeStamp) { m_SenderReport.RtpTimeStamp = TimeStamp; }
    void SetSenderReportSenderPacketCount(Uint32 Count) { m_SenderReport.SenderPacketCount = Count; }
    void SetSenderReportSenderOctetCount(Uint32 Count) { m_SenderReport.SenderOctetCount = Count; }
    void SetSenderReportAddBlock(const MkRtcpReportBlock& Block) { m_SenderReport.VecBlock.push_back(Block); SetCount(static_cast<Uint8>(m_SenderReport.VecBlock.size())); }

    const Uint32& GetReceptionSsrc() const { return m_ReceptionReport.Ssrc; }
    const MkVector<MkRtcpReportBlock>&  GetReceptionBlocks() const { return m_ReceptionReport.VecBlock; }

    void SetReceptionSsrc(Uint32 Ssrc) { m_ReceptionReport.Ssrc = Ssrc; }
    void ReceptionAddBlock(const MkRtcpReportBlock& Block) { m_ReceptionReport.VecBlock.push_back(Block); SetCount(static_cast<Uint8>(m_ReceptionReport.VecBlock.size())); }


    const MkMap<MkRtcpSdesType, MkRtcpSourceDescItem>& GetSourceDescriptionChunks()const { return m_SourceDescription.MapDescChunk; }
    const Uint32& GetSourceDescriptionSsrc()const { return m_SourceDescription.Ssrc; }
    void SetSourceDescriptionSsrc(Uint32 Ssrc) { m_SourceDescription.Ssrc = Ssrc; }
    void SetSourceDescriptionAddChunk(const MkRtcpSdesType& DescType, const MkString& DomainName);

    const MkVector<Uint32>& GetByeSsrc()const { return m_Bye.VecSsrc; }
    const MkString& GetByeReason()const { return m_Bye.Reason; }
    const Uint8& GetByeReasonLen()const { return m_Bye.ReasonLen; }
    void ByeAddSsrc(Uint32 Ssrc) { m_Bye.VecSsrc.push_back(Ssrc); }
    void SetByeReason(const MkString& Reason) { m_Bye.Reason = Reason; m_Bye.ReasonLen = static_cast<Uint8>(Reason.size()); }

    const Uint32& GetAppSsrc() const { return m_App.Ssrc; }
    const Uint32& GetAppName()const { return m_App.Name; }
    void SetAppSsrc(Uint32 Ssrc) { m_App.Ssrc = Ssrc; }
    void SetAppName(Uint32 Name) { m_App.Name = Name; }
    //Uint32 SetAppSubType(Uint8 SubType);
    MkString& GetAppData() { return m_App.AppDependentData; }
    void SetAppData(const MkString& Data) { m_App.AppDependentData = Data; m_App.DataLen = Data.size(); }

    Uint32 Packet(Uint8* pData, Uint32 nLen, Uint32& nUsed) const;
protected:
    Uint32 ParseSenderReport(const Uint8* pBuf, Uint32 nLen, Uint32& nUsed);
    Uint32 ParseReceptionReport(const Uint8* pBuf, Uint32 nLen, Uint32& nUsed);
    Uint32 ParseSourceDescription(const Uint8* pBuf, Uint32 nLen, Uint32& nUsed);
    Uint32 ParseBye(const Uint8* pBuf, Uint32 nLen, Uint32& nUsed);
    Uint32 ParseApp(const Uint8* pBuf, Uint32 nLen, Uint32& nUsed);

    Uint32 PacketSenderReport(Uint8* pBuf, Uint32 nLen, Uint32& nUsed) const;
    Uint32 PacketReceptionReport(Uint8* pBuf, Uint32 nLen, Uint32& nUsed) const;
    Uint32 PacketSourceDescription(Uint8* pBuf, Uint32 nLen, Uint32& nUsed) const;
    Uint32 PacketBye(Uint8* pBuf, Uint32 nLen, Uint32& nUsed) const;
    Uint32 PacketApp(Uint8* pBuf, Uint32 nLen, Uint32& nUsed) const;
private:
    /* common rtcp header
     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|    RC   |   PT=RR=201   |             length            |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */
    Uint8           m_Version;     //2bit
    Uint8           m_Padding;     //1bit
    Uint8           m_Count;       //5bit
    Uint8           m_Payload;     //1byte
    //Uint16          m_Length;      //2byte

    MkRtcpSenderReport          m_SenderReport;
    MkRtcpReceptionReport       m_ReceptionReport;
    MkRtcpSourceDescription     m_SourceDescription;
    MkRtcpByeParam              m_Bye;
    MkRtcpAppParam              m_App;
    //union
    //{

    //};
};

//https://datatracker.ietf.org/doc/rfc1889/
class MkApi CMkRtpPacket
{
public:
    CMkRtpPacket();
    ~CMkRtpPacket();
    Uint32 Parse(Uint8 *pData, Uint32 nLen);
    Uint32 PacketHeader(Uint8* pHeader, Uint32 nLen);
    const Uint8& GetVersion() const { return m_Version; }
    const Uint8& GetPadding() const { return m_Padding; }
    const Uint8& GetHasExtension()const { return m_HasExtension; }
    const Uint8& GetCsrcCount()const { return m_CsrcCount; }
    const Uint8& GetMaker()const { return m_bMaker; }
    const Uint8& GetPayload() const { return m_PayloadType; }
    const Uint16& GetSequenceNumber()const { return m_SequenceNumber; }
    const Uint32& GetSsrc()const { return m_Ssrc; }
    const Uint32& GetTimeStamp() const { return m_TimeStamp; }
    const MkVector<Uint32>& GetVecCsrc() const { return m_vecCsrc; }
    const Uint16& GetExtensionId()const { return m_ExtensionId; }
    const MkString& GetExtensionContent()const { return m_ExtensionContent; }
    Uint8* GetPayloadData() { return m_PlayloadData; }
    const Uint8* GetPayloadData() const { return m_PlayloadData; }
    const Uint32& GetPayloadLength() const { return m_nPlayloadDataLength; }
    const Uint8* GetHeaderData() const { return m_pHeader; }
    const Uint32& GetHeaderLen() const { return m_nHeaderLen; }
    const CMkBufferList& GetPayloadBufferList() const { return m_PayloadBufferList; }

    void SetVersion(Uint8 Version) { m_Version = Version; }
    void SetPadding(Uint8 Padding) { m_Padding = Padding; }
    void SetHasExtension(Uint8 Extension) { m_HasExtension = Extension; }
    void SetCsrcCount(Uint8 CsrcCount) { m_CsrcCount = CsrcCount; }
    void SetMarker(Uint8 Marker) { m_bMaker = Marker; }
    void SetPayloadType(Uint8 Payload) { m_PayloadType = Payload; }
    void SetSequenceNumber(Uint16 Number) { m_SequenceNumber = Number; }
    void SetSsrc(const Uint32& Ssrc) { m_Ssrc = Ssrc; }
    void SetTimeStamp(Uint32 TimeStamp) { m_TimeStamp = TimeStamp; }
    Uint32 AddCsrc(Uint32 Csrc);
    Uint32 SetCsrc(MkVector<Uint32>& VecCsrc);
    void SetExtensionId(Uint16 ExtId) { m_ExtensionId = ExtId; }
    void SetExtensionContent(const MkString& Content) { m_ExtensionContent = Content; }
    void SetPayloadData(Uint8* pData) { m_PlayloadData = pData; }
    void SetPayloadLength(Uint32 nLen) { m_nPlayloadDataLength = nLen; }
    void SetPayloadBufferList(const CMkBufferList& BufferList) { m_PayloadBufferList = BufferList; m_nPlayloadDataLength = m_PayloadBufferList.GetTatolLen(); }
    void AppentPayloadBufferList(const CMkBuffer& Buffer) { m_PayloadBufferList.Append(Buffer); m_nPlayloadDataLength = m_PayloadBufferList.GetTatolLen(); }
    void AppentPayloadBufferList(const Uint8* pBuffer, Uint32 nLen) { m_PayloadBufferList.Append(pBuffer, nLen); m_nPlayloadDataLength = m_PayloadBufferList.GetTatolLen(); }
    void ClearPayload();
protected:
private:
private:
    /*
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |V=2|P|X|  CC   |M|     PT      |       sequence number         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           synchronization source (SSRC) identifier            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |            contributing source (CSRC) identifiers             |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */
    Uint8               m_Version;          //2bit
    Uint8               m_Padding;          //1bit  
    Uint8               m_HasExtension;     //1bit
    Uint8               m_CsrcCount;        //4bit,max 0x0f
    Uint8               m_bMaker;           //1bit
    Uint8               m_PayloadType;      //7bit
    Uint16              m_SequenceNumber;   //2byte
    Uint32              m_TimeStamp;        //4byte
    Uint32              m_Ssrc;             //4byte

    MkVector<Uint32>    m_vecCsrc;          //size = m_CsrcCount
    Uint16              m_ExtensionId;
    MkString            m_ExtensionContent;

    Uint8               *m_PlayloadData;
    Uint32              m_nPlayloadDataLength;
    CMkBufferList       m_PayloadBufferList;

    Uint8               *m_pHeader;
    Uint32              m_nHeaderLen;
};

typedef MkFunction<Uint32(const CMkRtcpPacket& RtcpPacket, const MkString& Host, Uint16 Port)> MkRtcpPacketCallback;
typedef MkFunction<Uint32(const CMkRtpPacket& RtpPacket, const MkString& Host, Uint16 Port)> MkRtpPacketCallback;


#endif // !MK_RTP_UTIL_H